package com.qdxwx.data.service.user;

import com.qdxwx.common.page.PageRequest;
import com.qdxwx.common.utils.TKConvert;
import com.qdxwx.common.utils.TKString;
import com.qdxwx.data.mapper.account.UserAccountOptMapper;
import com.qdxwx.data.mapper.member.MemberRecordOptMapper;
import com.qdxwx.data.mapper.user.UserMapper;
import com.qdxwx.data.service.account.UserAccountDetailService;
import com.qdxwx.data.service.account.UserAccountService;
import com.qdxwx.data.service.card.CardCodeService;
import com.qdxwx.data.service.cash.CashApplyService;
import com.qdxwx.data.service.course.CourseStudyHistoryService;
import com.qdxwx.data.service.favorite.FavoriteService;
import com.qdxwx.data.service.manager.ManagerService;
import com.qdxwx.data.service.member.MemberRecordService;
import com.qdxwx.data.service.order.OrderAllotDetailService;
import com.qdxwx.data.service.order.OrderDetailService;
import com.qdxwx.data.service.order.OrderExpressService;
import com.qdxwx.data.service.order.OrderService;
import com.qdxwx.data.service.teacher.TeacherService;
import com.qdxwx.models.account.UserAccount;
import com.qdxwx.models.company.Company;
import com.qdxwx.models.enums.AccountStatus;
import com.qdxwx.models.enums.LetterTemplate;
import com.qdxwx.models.enums.UserRegisterFrom;
import com.qdxwx.models.manager.Manager;
import com.qdxwx.models.teacher.Teacher;
import com.qdxwx.models.user.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import jakarta.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * Qdx NetSchool Platform
 * @author qdxwx
 * @updateTime 2022/5/25
 * @description
 */
@Service
public class UserServiceImpl implements UserService {

	@Autowired
	private UserMapper userMapper;
	@Autowired
	private UserLoginService userLoginService;
	@Autowired
	private UserLetterService userLetterService;
	@Autowired
	private UserAccountService userAccountService;
	@Autowired
	private UserInviteService userInviteService;
	@Autowired
	private UserTokenService userTokenService;
	@Autowired
	private UserAccountDetailService userAccountDetailService;
	@Autowired
	private UserAccountOptMapper userAccountOptMapper;
	@Autowired
	private FavoriteService favoriteService;
	@Autowired
	private UserCountService userCountService;
	@Autowired
	private UserAddressService userAddressService;
	@Autowired
	private UserDownloadService userDownloadService;
	@Autowired
	private UserBuyService userBuyService;
	@Autowired
	private MemberRecordService memberRecordService;
	@Autowired
	private MemberRecordOptMapper memberRecordOptMapper;
	@Autowired
	private CardCodeService cardCodeService;
	@Autowired
	private CashApplyService cashApplyService;
	@Autowired
	private CourseStudyHistoryService courseStudyHistoryService;
	@Autowired
	private OrderAllotDetailService orderAllotDetailService;
	@Autowired
	private OrderDetailService orderDetailService;
	@Autowired
	private OrderExpressService orderExpressService;
	@Autowired
	private OrderService orderService;
	@Autowired
	private TeacherService teacherService;
	@Autowired
	private ManagerService managerService;

	@Override
	public int insert(User user) {
		user.setCreateTime(LocalDateTime.now());
		user.setLastLoginTime(LocalDateTime.now());
		int count = userMapper.insert(user);
		if (count < 1) {
			return 0;
		}
		// 添加账户
		UserAccount userAccount = new UserAccount();
		userAccount.setUserId(user.getUserId());
		userAccount.setBalance(0);
		userAccount.setFrozenAmount(0);
		userAccount.setAccountStatus(AccountStatus.ACTIVE.toString());
		userAccount.setVmAmount(0);
		userAccount.setBackAmount(0);
		userAccount.setVersion(0L);
		userAccountService.insert(userAccount);
		UserCount userCount = new UserCount();
		userCount.setId(user.getUserId());
		userCountService.insert(userCount);
		return count;
	}

	@Override
	public long insertByTeacher(Teacher teacher) {
		User user = new User();
		user.setMobile(teacher.getMobile());
		user.setLoginName(teacher.getMobile());
		user.setCompanyId(1);
		user.setAvatar(teacher.getAvatar());
		user.setUserName(teacher.getName());
		user.setRealName(teacher.getName());
		user.setPassword(TKConvert.toMD5("qdx123456"));
		user.setAge(0);
		user.setIsAvailable(1);
		user.setSex(1);
		user.setRegisterFrom(UserRegisterFrom.ADMIN.toString());
		insert(user);
		return user.getUserId();
	}

	@Override
	public long insertByManager(Manager manager) {
		User user = new User();
		user.setMobile(manager.getMobile());
		user.setLoginName(manager.getMobile());
		user.setCompanyId(manager.getCompanyId());
		user.setUserName(manager.getManagerName());
		user.setRealName(manager.getManagerName());
		user.setPassword(manager.getLoginPwd());
		user.setAge(0);
		user.setIsAvailable(1);
		user.setSex(1);
		user.setRegisterFrom(UserRegisterFrom.ADMIN.toString());
		insert(user);
		return user.getUserId();
	}

	/**
	 * 注册用户
	 */
	@Override
	public long register(HttpServletRequest request, User user) {
		//验证密码格式是否正确
		Company company = (Company) request.getAttribute("siteCompany");
		if (company != null) {
			user.setCompanyId(company.getCompanyId());
		}
		user.setIsAvailable(1);
		user.setPassword(TKConvert.toMD5(user.getPassword()));
		user.setLetterCount(0);
		int count = insert(user);
		if (count > 0) {
			//邀请码
			userInviteService.finishReg(user, request);
			// 注册时发送系统消息
			if (company != null) {
				userLetterService.send(user.getUserId(), LetterTemplate.USER_REGISTER, company.getSiteName());
			}
		}
		return user.getUserId();
	}

	@Override
	public User get(long userId) {
		if (userId < 1) return null;
		return userMapper.selectById(userId);
	}

	@Override
	public User getByCookie(String loginCookie) {
		if (loginCookie == null) return null;
		int indexOf = loginCookie.indexOf("|");
		if (indexOf < 1) return null;
		long uid = TKConvert.toLong(loginCookie.substring(0, indexOf));
		String token = loginCookie.substring(indexOf + 1);
		return getByToken(uid, token);
	}

	@Override
	public User getByToken(long userId, String token) {
		if (userId < 1 || token.length() < 32) return null;
		return userMapper.selectByToken(userId, token);
	}

	@Override
	public User getByMobile(String mobile) {
		if (TKString.isMobile(mobile)) {
			return userMapper.selectByMobile(mobile);
		}
		return null;
	}

	@Override
	public User getByLoginName(String name) {
		return userMapper.selectByLoginName(TKString.searchKeyFilter(name));
	}

	@Override
	public User getByEmail(String email) {
		if (TKString.isEmail(email)) {
			return userMapper.selectByEmail(email);
		}
		return null;
	}

	@Override
	public User getByAccount(String account) {
		if (TKString.isMobile(account)) {
			//验证账号为手机格式登陆时返回下面提示
			return userMapper.selectByMobile(account);
		} else if (TKString.isEmail(account)) {
			//验证账号为邮箱格式登陆时返回下面提示
			return userMapper.selectByEmail(account);
		} else {
			return userMapper.selectByLoginName(account);
		}
	}

	@Override
	public boolean isExistMobile(String mobile) {
		return getByMobile(mobile) != null;
	}

	@Override
	public boolean isExistLoginName(String loginName) {
		return getByLoginName(loginName) != null;
	}

	@Override
	public boolean isExistEmail(String email) {
		return getByEmail(email) != null;
	}

	@Override
	public void updateAvatar(User user) {
		userMapper.updateAvatar(user);
	}

	@Override
	public void updateUserPwd(User user) {
		userMapper.updateUserPwd(user);

	}

	@Override
	public void updateUserStatus(User user) {
		userMapper.updateUserStatus(user);
	}

	@Override
	public int update(User user) {
		return userMapper.updateUser(user);
	}

	@Override
	public void updateUserBannerUrl(User user) {
		userMapper.updateUserBannerUrl(user);
	}

	@Override
	public void updateLetterCount(Long userId, int count) {
		userMapper.updateLetterCount(userId, count);
	}

	@Override
	public void resetLetterCount(Long userId) {
		userMapper.resetLetterCount(userId);
	}

	@Override
	public void updateLoginTime(long userId) {
		if (userId < 1) return;
		userMapper.updateLoginTime(userId, LocalDateTime.now());
	}

	@Override
	public List<User> getList(UserQuery user, PageRequest page) {
		return userMapper.selectList(user, page);
	}

	@Override
	public long count(UserQuery user) {
		return userMapper.selectCount(user);
	}

	@Override
	public int deleteUserByIds(String ids) {
		if (TKString.isEmpty(ids)) return 0;
		String[] idsArr = TKConvert.toStrArray(ids);
		int row = userMapper.deleteUserByIds(TKConvert.toStrArray(ids));
		if (row > 0) userAccountService.deleteByIds(idsArr);
		return row;
	}

	/**
	 * 更新登录时间，生成登录日志，并返回新的UserToken，不写Session,Cookie
	 */
	@Override
	public UserToken doLogin(HttpServletRequest request, User user) {
		//更新登录时间
		user.setLoginTime(LocalDateTime.now());
		userMapper.updateLoginTime(user.getUserId(), user.getLoginTime());
		userLoginService.create(request, user);
		return userTokenService.create(user.getUserId());
	}

	@Override
	public int combine(long targetId, long sourceId) {
		User user = get(sourceId);
		if (user == null) return 0;
		return combine(targetId, user);
	}

	@Override
	@Transactional(rollbackFor = RuntimeException.class)
	public int combine(long targetId, User sourceUser) throws RuntimeException {
		User user = get(targetId);
		if (user == null || sourceUser == null) {
			throw new RuntimeException("账户异常");
		}
		if (sourceUser.getIsAvailable() == 2) {
			throw new RuntimeException("绑定手机存在禁用账户");
		}
		try {
			//更新教师
			teacherService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新管理员
			managerService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新收货地址
			userAddressService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新课程
			userBuyService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新下载记录
			userDownloadService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新邀请
			userInviteService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新收藏
			favoriteService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新站内信息
			userLetterService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新卡
			cardCodeService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新提现
			cashApplyService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新学习记录
			courseStudyHistoryService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新返现订单
			orderAllotDetailService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新订单详情
			orderDetailService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新配送订单
			orderExpressService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新订单
			orderService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新会员
			memberRecordService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新后台会员延期操作
			memberRecordOptMapper.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新统计
			userCountService.updateCombine(user.getUserId(), userCountService.get(sourceUser.getUserId()));
			//合并账户资金
			userAccountService.updateCombine(user.getUserId(), userAccountService.getByUserId(sourceUser.getUserId()));
			//更新账户详情
			userAccountDetailService.updateCombine(user.getUserId(), sourceUser.getUserId());
			//更新后台账户操作
			userAccountOptMapper.updateCombine(user.getUserId(), sourceUser.getUserId());
			//删除账户2
			userAccountService.delete(sourceUser.getUserId());
			//删除统计2
			userCountService.delete(sourceUser.getUserId());
			//删除用户2
			return userMapper.deleteById(sourceUser.getUserId());
		} catch (RuntimeException e) {
			throw new RuntimeException(e.getMessage());
		}
	}

	@Override
	public int updateMobile(User user) {
		return userMapper.updateMobile(user);
	}

	@Override
	public List<User> getLatelyStudentList(int courseId, PageRequest page) {
		return userMapper.selectLatelyStudentList(courseId, page);
	}

	@Override
	public List<User> getLatelyStudentList(int courseId, int limit) {
		return getLatelyStudentList(courseId, new PageRequest(1, limit));
	}

	@Override
	public List<User> getStudentList(int courseId, PageRequest page) {
		return userMapper.selectStudentList(courseId, page);
	}

	@Override
	public int countStudent(int courseId) {
		return userMapper.countStudent(courseId);
	}

	@Override
	public List<User> getMyStudentList(long userId, PageRequest page) {
		if(userId < 1) return new ArrayList<>();
		return userMapper.selectMyStudentList(userId, page);
	}

	@Override
	public int countMyStudent(long userId) {
		if(userId < 1) return 0;
		return userMapper.countMyStudent(userId);
	}
}
